package com.wulis.seckill.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wulis.seckill.common.util.ThreadPoolUtil;
import com.wulis.seckill.enums.SecKillInventoryEnum;
import com.wulis.seckill.business.mapper.SeckillGoodsInfoMapper;
import com.wulis.seckill.business.pojo.SeckillGoodsInfo;
import com.wulis.seckill.business.service.SeckillGoodsInfoService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 库存秒杀管理
 */
@Slf4j
@Service
@AllArgsConstructor
public class SeckillGoodsInfoServiceImpl
        extends ServiceImpl<SeckillGoodsInfoMapper, SeckillGoodsInfo>
        implements SeckillGoodsInfoService {

    private final SeckillGoodsInfoMapper seckillGoodsInfoMapper;

    private final CacheStockServiceImpl cacheStockService;

    private final ThreadPoolExecutor threadPoolExecutor = ThreadPoolUtil.getBoundedThreadPool();

    public volatile static int a = 0;

    /**
     * 保存秒杀数据到redis缓存
     */
    public void cacheStock() {
        QueryWrapper<SeckillGoodsInfo> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(SeckillGoodsInfo::getDeleteFlag, "1");
        List<SeckillGoodsInfo> seckillGoodsInfos = seckillGoodsInfoMapper.selectList(queryWrapper);
        seckillGoodsInfos.forEach(p -> {
            String code = cacheStockService.addStock(String.valueOf(p.getGoodsId()), p.getCount());
            if (SecKillInventoryEnum.SEC_KILL_ERROR.code().equals(code)) {
                log.error("秒杀商品保存失败，商品id:{}", p.getGoodsId());
            }
        });
    }

    /**
     * 查看缓存秒杀商品数据
     *
     * @param goodsId
     * @return
     */
    public Map getCacheStock(Long goodsId) {
        Map map = new HashMap();
        if (goodsId != null) {
            map.put(goodsId, cacheStockService.getStock(String.valueOf(goodsId)));
            return map;
        }
        QueryWrapper<SeckillGoodsInfo> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(SeckillGoodsInfo::getDeleteFlag, "1");
        List<SeckillGoodsInfo> seckillGoodsInfos = seckillGoodsInfoMapper.selectList(queryWrapper);
        seckillGoodsInfos.forEach(p -> {
            int stock = cacheStockService.getStock(String.valueOf(p.getGoodsId()));
            map.put(p.getGoodsId(), stock);
        });
        return map;
    }

    /**
     * 秒杀商品
     *
     * @param goodsId
     * @param num
     * @return
     */
    public String lightningDeals(Long goodsId, int num) {
        String userId = UUID.randomUUID().toString().replaceAll("-", "");
        //减少缓存库存数量
        String code = cacheStockService.reduceStock(String.valueOf(goodsId), num, userId);
        //TODO 异步消息减少数据库库存(可修改成mq消息队列去处理)
        if (SecKillInventoryEnum.SEC_KILL_SUCCESS.code().equals(code)) {
            threadPoolExecutor.execute(() -> {
                reduceStock(goodsId, userId);
            });
        }
        return code;
    }

    public synchronized void reduceStock(Long goodsId, String userId) {
        SeckillGoodsInfo seckillGoods = seckillGoodsInfoMapper.selectById(goodsId);
        if (seckillGoods == null) {
            return;
        }
        seckillGoodsInfoMapper.reduceStock(seckillGoods.getGoodsId(),
                seckillGoods.getVersion());
        log.info("商品秒杀成功,商品id：{},商户id:{},扣减次数:{}", goodsId, userId, ++a);
    }

}
